﻿using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using System.Linq;
using System.Linq.Expressions;
using System;
#if NETFX_CORE
using Dispatcher = Windows.UI.Core.CoreDispatcher;
using Windows.UI.Xaml;
#else
using System.Windows.Threading;
#endif

namespace UnitDriven
{
	public class ObservableObject : INotifyPropertyChanged
	{
#if !__ANDROID__
		private Dispatcher dispatcher;

		protected Dispatcher Dispatcher
		{
			get { return this.dispatcher; }
		}
#endif
        
        public ObservableObject()
		{
#if NETFX_CORE
            this.dispatcher = Window.Current.Dispatcher;
#elif !__ANDROID__
			this.dispatcher = System.Windows.Application.Current.Resources.Dispatcher;
#endif
		}
        
        public event PropertyChangedEventHandler PropertyChanged = (o, e) => { };

        protected void Set<T>(ref T field, T value, params Expression<Func<object>>[] propertyReferences)
        {
            if (!object.ReferenceEquals(field, value))
            {
                field = value;
                OnPropertyChanged(propertyReferences);
            }
        }

        protected void OnPropertyChanged(params Expression<Func<object>>[] properties)
        {
            var names = properties.Select(p => ((MemberExpression)p.Body).Member.Name).ToArray();
            OnPropertyChanged(names);
        }

        protected void OnPropertyChanged(params string[] properties)
        {
            foreach (var name in properties)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }

#if NETFX_CORE        
        protected void UpdateAll()
        {
            this.OnPropertyChanged(this.GetType()
                .GetTypeInfo()
                .DeclaredProperties
                .Select(p => p.Name)
                .ToArray());
        }
#else
#endif
	}
}
